/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ru.ssau.berlin.jsf.beans;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import javax.ejb.EJB;
import javax.faces.event.ActionEvent;
import javax.faces.model.SelectItem;
import org.apache.log4j.Logger;
import ru.ssau.berlin.ejb.facade.GroupFacadeLocal;
import ru.ssau.berlin.ejb.facade.UniFacadeLocal;
import ru.ssau.berlin.entity.AttributeType;
import ru.ssau.berlin.entity.GroupAttribute;
import ru.ssau.berlin.entity.GroupType;
import ru.ssau.berlin.jsf.util.FacesApplication;


/**
 *
 * @author Пользователь
 */
public class GroupTypeView {

    private final static Logger log = Logger.getLogger(GroupTypeView.class);

    private static final String ID_PARAMETER = "id_param";

    @EJB
    private GroupFacadeLocal groupFacade;
    @EJB
    private UniFacadeLocal uniFacade;

    private FacesApplication application = FacesApplication.getInstance();

    private List<GroupType> types;
    private GroupType type;
    private boolean readonly;
    private List<SelectItem> items;
    private List<GroupAttribute> attrs;
    private GroupAttribute attr;
    private List<SelectItem> attrItems;
    private List<AttributeType> attrTypes;
    private ArrayList<SelectItem> attrTypeItems;
   
    public List<GroupType> getTypes() {
        return types;
    }

    public void setTypes(List<GroupType> types) {
        this.types = types;
    }

    public GroupType getType() {
        return type;
    }

    public void setType(GroupType type) {
        this.type = type;
    }

    public boolean isReadonly() {
        return readonly;
    }

    public void setReadonly(boolean readonly) {
        this.readonly = readonly;
    }

    public GroupAttribute getAttr() {
        return attr;
    }

    public void setAttr(GroupAttribute attr) {
        this.attr = attr;
    }

    public List<SelectItem> getAttrItems() {
        return attrItems;
    }

    public void setAttrItems(List<SelectItem> attrItems) {
        this.attrItems = attrItems;
    }

    public List<GroupAttribute> getAttrs() {
        return attrs;
    }

    public void setAttrs(List<GroupAttribute> attrs) {
        this.attrs = attrs;
    }

    public List<SelectItem> getItems() {
        return items;
    }

    public void setItems(List<SelectItem> items) {
        this.items = items;
    }

    public ArrayList<SelectItem> getAttrTypeItems() {
        return attrTypeItems;
    }

    public String showAll() {
        types = groupFacade.findGroupTypes();
        return application.getNavigator().goToGroupTypes();
    }

    public String show() {
        type = groupFacade.findGroupType(Long.parseLong(
                application.getRequestParameter(ID_PARAMETER)));
        types = new ArrayList<GroupType>(2);
        readonly = true;
        generateGroupTypeSelectItems();
        attrs = type.getAttributes();
        generateAttributeSelectItems();
        return application.getNavigator().goToGroupType();
    }

    public String edit() {
        log.info("Finding GroupType...");
        type = groupFacade.findGroupType(Long.parseLong(
                application.getRequestParameter(ID_PARAMETER)));
        log.info("GroupType found");
        log.info("Retrieving all GroupType...");
        types = groupFacade.findGroupTypes();
        log.info("All instances of GroupType retrieved");
        log.info("Removing children...");
        types.remove(type);
        removeChildren();
        log.info("Children removed");
        log.info("Generating GroupType select item...");
        generateGroupTypeSelectItems();
        log.info("Select items generated");
        log.info("Finding all instances of GroupAttribute...");
        attrs = groupFacade.findGroupAttributes();
        log.info("All instances of GroupAttribute found");
        log.info("Cleaning parent and binded attributes...");
        GroupType curr = type;
        while (curr != null) {
            attrs.removeAll(curr.getAttributes());
            curr = curr.getParent();
        }
        log.info("Attributes cleaned");
        log.info("Generating GroupAttribute select items...");
        generateAttributeSelectItems();
        log.info("Select items generated");
        log.info("Redirecting...");
        readonly = false;
        return application.getNavigator().goToGroupType();
    }

    public void delete(ActionEvent event) {
        groupFacade.removeType(groupFacade.findGroupType(Long.parseLong(
                event.getComponent().getAttributes().get(ID_PARAMETER).toString())));
    }

    public String create() {
        type = new GroupType();
        types = groupFacade.findGroupTypes();
        generateGroupTypeSelectItems();
        readonly = false;
        return application.getNavigator().goToGroupType();
    }

    public String persist() {
        if (type.getId() == null) {
            groupFacade.createType(type);
        } else {
            groupFacade.editType(type);
        }
        return showAll();
    }

    public String createAttribute() {
        attr = new GroupAttribute();
        readonly = false;
        return application.getNavigator().goToGroupAttribute();
    }

    public String persistAttribute() {
        if (attr.getId() == null) {
            groupFacade.createAttribute(attr);
            if (type != null) {
                type.getAttributes().add(attr);
                groupFacade.editType(type);
            }
        } else {
            groupFacade.editAttribute(attr);
        }
        return application.getNavigator().goToGroupType();
    }

    public String editAttribute() {
        loadAttribute();
        attrTypes = uniFacade.findAttributeTypes();
        generateAttributeTypeSelectItems();
        readonly = false;
        return application.getNavigator().goToPersonAttribute();
    }

    public void deleteAttribute(ActionEvent event) {
        attr = groupFacade.findGroupAttribute(Long.parseLong(
                event.getComponent().getAttributes().get(ID_PARAMETER).toString()));
        groupFacade.removeAttribute(attr);
        attrs = groupFacade.findGroupAttributes();
    }

    public String showAllAttributes() {
        attrs = groupFacade.findGroupAttributes();
        return application.getNavigator().goToGroupAttributes();
    }

    public String addAttribute() {
        type.getAttributes().add(attr);
        groupFacade.editType(type);
        attrs = groupFacade.findGroupAttributes();
        GroupType currType = type;
        while (currType != null) {
            attrs.removeAll(currType.getAttributes());
            currType = currType.getParent();
        }
        generateAttributeSelectItems();
        return application.getNavigator().stayHere();
    }

    private void loadAttribute() {
        attr = groupFacade.findGroupAttribute(Long.parseLong(
                application.getRequestParameter(ID_PARAMETER)));
    }

    private void generateAttributeTypeSelectItems() {
        attrTypeItems = new ArrayList<SelectItem>(attrTypes.size());
        for (AttributeType iter: attrTypes) {
            attrTypeItems.add(new SelectItem(iter, iter.getName()));
        }
    }

    public String unbindAttribute() {
        if (type != null) {
            loadAttribute();
            type.getAttributes().remove(attr);
            groupFacade.editType(type);
            attrs = groupFacade.findGroupAttributes();
            GroupType currType = type;
            while (currType != null) {
                attrs.removeAll(currType.getAttributes());
                currType = currType.getParent();
            }
            generateAttributeSelectItems();
        }
        return application.getNavigator().stayHere();
    }

    private void removeChildren() {
        List<GroupType> toRemove = collectChildren(type);
        types.removeAll(toRemove);
    }

    private List<GroupType> collectChildren(GroupType type) {
        List<GroupType> children = new LinkedList<GroupType>();
        for (GroupType child : type.getChildren()) {
            children.addAll(collectChildren(child));
        }
        children.addAll(type.getChildren());
        return children;
    }

    private void generateGroupTypeSelectItems() {
        items = new ArrayList<SelectItem>(types.size());
        for (GroupType iter: types) {
            items.add(new SelectItem(iter, iter.toString()));
        }
    }

    private void generateAttributeSelectItems() {
        attrItems = new ArrayList<SelectItem>(attrs.size() + 1);
        for (GroupAttribute attribute: attrs) {
            attrItems.add(new SelectItem(attribute, attribute.getName()));
        }
    }

}
